﻿//---------------------------------------------------------------------------
//
// Copyright (C) Inter Access B.V..  All rights reserved.
//
//---------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;

namespace Schedule.Primitives
{
    /// <summary>
    /// Observer used to observe the TimeItem
    /// This class is used to keep track of interacting TimeItems
    /// </summary>
    public class TimeItemObserver
    {
        private ObservableCollection<TimeItem> _intersectedItems;
        private TimePanel _panel;
        private TimeItem _item;

        /// <summary>
        /// Constructs a TimeItemObserver
        /// </summary>
        /// <param name="item">TimeItem to observe</param>
        /// <param name="panel">TimePanel wich the item belongs to</param>
        public TimeItemObserver(TimeItem item, TimePanel panel)
        {
            _item = item;
            _panel = panel;
            _item.Owner = panel;

            _intersectedItems = new ObservableCollection<TimeItem>();

            //foreach (TimeItem timeItem in GetIntersectedItems())
            //{
            //    _intersectedItems.Add(timeItem);
            //}
            //ArrangeItemFirstPass();

            //IntersectedItems.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(IntersectedItems_CollectionChanged);
        }

        /// <summary>
        /// Item wich is observed
        /// </summary>
        public TimeItem Item
        {
            get { return _item; }
        }

        /// <summary>
        /// Parent panel wich the item belongs to
        /// </summary>
        public TimePanel Panel
        {
            get { return _panel; }
        }


        #region Methods

        public void ArrangeItemFirstPass()
        {
            List<TimeItem> _sortedItems = IntersectedItems.ToList<TimeItem>();
            _sortedItems.Sort(new TimeItemComparer());
            int position = _sortedItems.IndexOf(Item);
            if (Panel.Columns < _sortedItems.Count) Panel.Columns = _sortedItems.Count;
            int defaultColumnsSpan = (int)Math.Floor((Double)(Panel.Columns / _sortedItems.Count));

            if (position == 0)
            {
                // We are the first item, set column to 0
                TimePanel.SetColumn(Item, 0);
                if (_sortedItems.Count == 1)
                {
                    // If we are the only item
                    TimePanel.SetColumnSpan(Item, Panel.Columns);
                }
                else
                {
                    // Just set column span to default
                    TimePanel.SetColumnSpan(Item, defaultColumnsSpan);
                }
            }
            else
            {
                int columnMask = (1 << Panel.Columns) - 1;
                foreach (TimeItem parentItem in _sortedItems)
                {
                    if (parentItem == Item) break;
                    int startColumn = TimePanel.GetColumn(parentItem);
                    int endColumn = TimePanel.GetColumnSpan(parentItem) + startColumn;

                    for (int column = startColumn; column < endColumn; column++)
                    {
                        columnMask = columnMask | 1 << column;
                    }
                }

                int targetColumn = 0;
                while(((1 << targetColumn) & columnMask) == (1 << targetColumn))
                {
                    targetColumn++;
                }
                if (Panel.Columns < targetColumn + 1) Panel.Columns = targetColumn + 1;
                TimePanel.SetColumn(Item, targetColumn);
                TimePanel.SetColumnSpan(Item, defaultColumnsSpan);
            }
        }

        private void IntersectedItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            ArrangeItemFirstPass();
        }

        public bool Intersects(TimeItem item)
        {
            return TimePanel.GetItemStart(Item) < TimePanel.GetItemEnd(item) &&
                    TimePanel.GetItemEnd(Item) > TimePanel.GetItemStart(item) &&
                    (TimePanel.GetItemStart(Item) - TimePanel.GetItemEnd(Item)) >= (TimePanel.GetItemStart(item) - TimePanel.GetItemEnd(item));
        }

        public ObservableCollection<TimeItem> IntersectedItems
        {
            get { return _intersectedItems; }
        }

        private List<TimeItem> GetIntersectedItems()
        {
            var result = from timeItems in Panel.Children.OfType<TimeItem>()
                      where Intersects(timeItems)
                      select timeItems;

            return result.ToList<TimeItem>();
        }

        #endregion
    }
}
